/*
 * Created on 07.12.2003
 */
package observations;

import java.util.*;

/**
 <code>Patient</code> Represents a patient with all associated data and
 * grants retrieval of phenomena, measurements and observations.
 
 @author Sascha Hemminger
 @version 2004-09-10
 */
public class Patient extends DomainObject {

  /**
   * Use this one to search a patient by name.
   
   @param name
   *            name of patient to search
   @return Patient if found else null
   */
  public static Patient get(String name) {
    return (PatientRegistrar.get("Patient", name);
  }

  private Vector allObservations = new Vector();

  private Observation observations;

  /**
   * Default constructor constructs a new patient object with name.
   
   @param name
   *            the patient's name 'John Doe'
   @see observations.DomainObject#DomainObject(String)
   */
  public Patient(String name) {
    super(name);
  }

  /**
   * Use this to search the latest amount observed and saved of a particular
   * type.
   
   @param value
   *            PhenomenonType to get the latest amount for
   @return latest amount for PhenomenonType
   */
  public Quantity getLatestAmountOf(PhenomenonType value) {
    Measurement latestMeasurement = (MeasurementgetLatestObservation(value);
    return (latestMeasurement == nullnew NullQuantity()
        : latestMeasurement.amount();
  }

  /**
   * Use this to search the latest observation made on a particular
   * phenomenon.
   
   @param value
   *            Phenomenon to get the latest Obs for
   @return latest Obs for Phenomenon
   */
  public Observation getLatestObservation(Phenomenon value) {
    return latestObservationIn(getObservationsOf(value));
  }

  /**
   * Gives the latest observation made on a particular type.
   
   @param value
   *            PhenomenonType to get the latest Obs for
   @return latest Obs of PhenomenonType
   */
  public Observation getLatestObservation(PhenomenonType value) {
    return latestObservationIn(getObservationsOf(value));
  }

  /**
   * Gives the latest observations made.
   
   @return latest observation
   @see #setObservations(Observation)
   */
  public Observation getObservations() {
    return observations;
  }

  /**
   * Returns all present observations.
   
   @return all Observations
   */
  public Enumeration getObservationsEnumeration() {
    return allObservations.elements();
  }

  /**
   * Returns all observations made on a particular phenomenon.
   
   @param value
   *            Phenomenon to get all Observations for
   @return an enumeration of all Obs for Phenomenon
   */
  public Enumeration getObservationsOf(Phenomenon value) {
    Vector result = new Vector();
    Enumeration e = getObservationsEnumeration();
    while (e.hasMoreElements()) {
      Observation each = (Observatione.nextElement();
      if (each.getPhenomenon() == value)
        result.addElement(each);
    }
    return result.elements();
  }

  /**
   * Returns all observations made of a particular phenomenon.
   
   @param value
   *            PhenomenonType to get all Observations for
   @return an enumeration of all Obs for PhenomenonType
   */
  public Enumeration getObservationsOf(PhenomenonType value) {
    Vector result = new Vector();
    Enumeration e = getObservationsEnumeration();
    while (e.hasMoreElements()) {
      Observation each = (Observatione.nextElement();
      if (each.getPhenomenonType() == value)
        result.addElement(each);
    }
    return result.elements();
  }

  /**
   * Gives the phenomenon for a particular type.
   
   @param phenomenonType
   *            which PhenomenonType to search
   @return particular Phenomenon for PhenomenonType for this Patient
   */
  public Phenomenon getPhenomenonOf(PhenomenonType phenomenonType) {
    return (getLatestObservation(phenomenonType)) == null new NullPhenomenon()
        : getLatestObservation(phenomenonType).getPhenomenon();
  }

  /**
   * Gives the phenomenon for a type. The type is searched by name.
   
   @param name
   *            name of the type of Phenomenon to search
   @return particular Phenomenon for this Patient
   */
  public Phenomenon getPhenomenonOf(String name) {
    return getPhenomenonOf(PhenomenonType.get(name));
  }

  /**
   * If a phenomenon is present its the latest observed.
   
   @param value
   *            Phenomenon to check whether it is present
   @return true if present
   */
  public Boolean isPresent(Phenomenon value) {
    return (getLatestObservation(value== null null new Boolean(
        getLatestObservation(value).isPresent()));
  }

  private Observation latestObservationIn(Enumeration observationEnum) {
    if (!observationEnum.hasMoreElements())
      return null;
    Observation result = (ObservationobservationEnum.nextElement();
    if (!observationEnum.hasMoreElements())
      return result;
    do {
      Observation each = (ObservationobservationEnum.nextElement();
      if (each.whenObserved().after(result.whenObserved()))
        result = each;
    while (observationEnum.hasMoreElements());
    return result;
  }

  /**
   * Adds a new observation.
   
   @param newObs
   *            add a new observed Observation to this Patient's Observations
   */
  public void observationsAdd(Observation newObs) {
    allObservations.addElement(newObs);
  }

  /**
   * Registers a patient, means saves patient to memory.
   
   @return the saved patient
   */
  public Patient persist() {
    Registrar.add("Patient"this);
    return this;
  }

  /**
   * Sets the latest observation.
   
   @param observations
   *            latest observation made
   @see #getObservations()
   */
  public void setObservations(Observation observations) {
    this.observations = observations;
  }

}